package com.zmn.oms.zmn.normal.business.impl.work.financework;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.zmn.base.channel.common.dro.ChannelCommissionDRO;
import com.zmn.base.channel.dubbo.interfaces.channel.commission.param.ChannelCommissionParamListRemoteService;
import com.zmn.base.common.data.common.dro.company.CompanyDRO;
import com.zmn.base.common.data.dubbo.interfaces.company.CompanyListRemoteService;
import com.zmn.base.engineer.common.dro.foreign.engineer.ForeignEngineerDetailInfoDRO;
import com.zmn.base.engineer.dubbo.interfaces.foreign.EngineerListRemoteService;
import com.zmn.base.plat.engine.common.constant.CompanyConsts;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.math.MathUtil;
import com.zmn.common.utils.math.MoneyUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.erp.common.newbiz.dto.master.AddMoreOrderBonusDTO;
import com.zmn.manager.mq.interfaces.ZmnMQSender;
import com.zmn.oms.business.interfaces.messageV1.common.MessageGetSendInfoService;
import com.zmn.oms.business.interfaces.orderamount.OrderDiscountCalcBService;
import com.zmn.oms.business.interfaces.remark.OrderRemarkBService;
import com.zmn.oms.business.interfaces.work.OrderWorkListBService;
import com.zmn.oms.common.annotation.ZsNormalOrderWorkLog;
import com.zmn.oms.common.constant.MessageQueueTagConsts;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderLogConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.dto.OmsOperator;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.constant.MessageQueueTopicConstant;
import com.zmn.oms.model.dto.work.modify.InvoiceInfoRefundBO;
import com.zmn.oms.model.dto.work.modify.ZsSyncAccountDIO;
import com.zmn.oms.model.dto.work.modify.erp.*;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.part.OrderPart;
import com.zmn.oms.model.entity.serviceitem.OrderServiceItem;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkQuery;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.factory.OrderFactoryService;
import com.zmn.oms.services.interfaces.order.OrderExtendService;
import com.zmn.oms.services.interfaces.part.OrderPartService;
import com.zmn.oms.services.interfaces.serviceitem.OrderServiceItemService;
import com.zmn.oms.services.interfaces.work.OrderWorkAmountService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.services.interfaces.work.financework.FinanceWorkService;
import com.zmn.oms.zmn.business.interfaces.part.ZsOrderPartBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkOperatePermissionBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkQueryBService;
import com.zmn.oms.zmn.business.interfaces.work.orderpay.ZsOrderPayBService;
import com.zmn.oms.zmn.normal.business.interfaces.discount.ZsNormalOrderDiscountBService;
import com.zmn.oms.zmn.normal.business.interfaces.part.ZsNormalOrderPartBService;
import com.zmn.oms.zmn.normal.business.interfaces.work.ZsNormalWorkBService;
import com.zmn.oms.zmn.normal.business.interfaces.work.customwork.ZsNormalCustomWorkBService;
import com.zmn.oms.zmn.normal.business.interfaces.work.financework.ZsNormalErpFinanceWorkBService;
import com.zmn.oms.zmn.normal.business.interfaces.work.financework.ZsNormalFinanceWorkBService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @author sunlife
 * @date:2020/9/16 11:18 上午
 * description:
 */
@Service
@Slf4j
public class ZsNormalErpFinanceWorkBServiceImpl implements ZsNormalErpFinanceWorkBService {

    @Autowired
    ZsOrderWorkQueryBService zsOrderWorkQueryBService;
    @Autowired
    OrderExtendService orderExtendService;
    @Autowired
    ZsNormalFinanceWorkBService zsNormalFinanceWorkBService;
    @Autowired
    ZsNormalOrderPartBService zsNormalOrderPartBService;
    @Autowired
    ZsNormalCustomWorkBService zsNormalCustomWorkBService;
    @Autowired
    ZsNormalWorkBService zsNormalWorkBService;
    @Autowired
    OrderWorkService orderWorkService;
    @Autowired
    ZsOrderWorkOperatePermissionBService orderWorkOperatePermissionBService;
    @Autowired
    ZsOrderPartBService zsOrderPartBService;
    @Autowired
    OrderWorkAmountService orderWorkAmountService;
    @Autowired
    private OrderRemarkBService orderRemarkBService;
    @Autowired
    private OrderServiceItemService orderServiceItemService;
    @Resource
    private ZmnMQSender zmnMQSender;
    @Autowired
    OrderWorkListBService orderWorkListBService;
    @Autowired
    OrderDetailService orderDetailService;
    @Autowired
    OrderDiscountCalcBService orderDiscountCalcBService;
    @Autowired
    MessageGetSendInfoService messageGetSendInfoService;
    @Autowired
    ZsNormalErpFinanceWorkBService zsNormalErpFinanceWorkBService;
    @Autowired
    OrderFactoryService orderFactoryService;
    @Autowired
    ZsOrderPayBService zsOrderPayBService;
    @Autowired
    FinanceWorkService financeWorkService;
    @Autowired
    ZsNormalOrderDiscountBService zsNormalOrderDiscountBService;
    @Autowired
    OrderPartService orderPartService;

    @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    EngineerListRemoteService engineerListRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    CompanyListRemoteService companyListRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    ChannelCommissionParamListRemoteService channelCommissionParamListRemoteService;


    private static final String INVOICE_MQ_TAG = "invoice_info_refund";


    @Override
    public void syncAccount(ZsSyncAccountDIO accountDIO) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(accountDIO.getOrderId(), accountDIO.getWorkId());
        if (Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_ACCOUNT)) {
            return;
        }

        if (!Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_F)) {
            zsNormalErpFinanceWorkBService.saveAccount(accountDIO);
        } else {
            zsNormalErpFinanceWorkBService.saveFAccount(accountDIO);
        }

        // 算账后删除redis删除百度表单id
        messageGetSendInfoService.deleteOrderBaiduSceneIds(orderWork.getOrderId());
        // 清除redis中缓存的特殊优惠券
        orderDiscountCalcBService.delRedisSpecialDiscountCoupon(orderWork.getOrderId());
        // 删除优惠信息及报价标示
        zsNormalOrderDiscountBService.deleteOrderMasterApplyDiscountAndQuotation(orderWork.getWorkId(), orderWork.getMasterId());

        try {
            boolean canBonus = this.canBonus(orderWork);
            log.info("工单[{}]是否是师傅恶意加单：{}", orderWork.getWorkId(), canBonus ? "否" : "是");
            if (canBonus) {
                this.sendAddMasterBonus(orderWork);
            }
        } catch (Exception e) {
            log.error("加单异常{}", orderWork.getWorkId(), e);
        }

        // 退款单发送开发票信息
        sendInvoiceInfo(orderWork, accountDIO);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_ACCOUNT, beforeProceed = false)
    public void saveAccount(ZsSyncAccountDIO accountDIO) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(accountDIO.getOrderId(), accountDIO.getWorkId());
        Date accountTime = DateUtil.getNow();
        Integer channelAmount = null;
        try {
            channelAmount = this.calcChannelAmount(orderWork);
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
        // 2，保存工单算账  -- 保留
        log.info("[{}]算账step2，保存工单算账", orderWork.getWorkId());
        OrderWork accountOrderWork = new OrderWork();
        accountOrderWork.setOrderId(accountDIO.getOrderId());
        accountOrderWork.setWorkId(accountDIO.getWorkId());
        accountOrderWork.setAccountTime(Optional.ofNullable(accountDIO.getAccountTime()).orElse(DateUtil.getNow()));
        accountOrderWork.setAccounterId(accountDIO.getOperatorId());
        accountOrderWork.setStatus(OrderStatusConsts.WORK_STATUS_ACCOUNT);
        accountOrderWork.setCurrentRemark(accountDIO.getOperatorRemark());
        accountOrderWork.setChannelAmount(channelAmount);
        accountOrderWork.setAccountId(accountDIO.getAccountId());
        financeWorkService.updateAccount(accountOrderWork);
        // 写日志设置状态
        accountDIO.setStatus(accountOrderWork.getStatus());

//        this.processLog(orderWork, accountDIO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_ACCOUNT, beforeProceed = false)
    public void saveFAccount(ZsSyncAccountDIO accountDIO) throws OmsBaseException {
        log.info("[{}]算账step0，线程id[{}]", accountDIO.getWorkId(), Thread.currentThread().getId());
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(accountDIO.getOrderId(), accountDIO.getWorkId());

        // 保存工单算账信息
        log.info("[{}]算账step1，保存工单算账", orderWork.getWorkId());
        OrderWork accountOrderWork = new OrderWork();
        accountOrderWork.setOrderId(accountDIO.getOrderId());
        accountOrderWork.setWorkId(accountDIO.getWorkId());
        accountOrderWork.setAccountTime(DateUtil.getNow());
        accountOrderWork.setAccounterId(accountDIO.getOperatorId());
        accountOrderWork.setStatus(OrderStatusConsts.WORK_STATUS_ACCOUNT);
        accountOrderWork.setCurrentRemark(accountDIO.getOperatorRemark());
        accountOrderWork.setAccountId(accountDIO.getAccountId());
        financeWorkService.updateAccount(accountOrderWork);
        // 写日志设置状态
        accountDIO.setStatus(accountOrderWork.getStatus());
        //算账日志
//        this.processLog(orderWork, accountDIO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_ACCOUNT, beforeProceed = false)
    public void autoAccount(ZsSyncAccountDIO accountDIO) throws Exception {
        log.info("[{}]过期工单自动算账step0，线程id[{}]", accountDIO.getWorkId(), Thread.currentThread().getId());
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(accountDIO.getOrderId(), accountDIO.getWorkId());

        String remark = "工单已到强制完结时间，系统自动变更订单状态为：已算账；若需给服务商或工程师分润，请走线下流程。";

        // 保存工单算账信息
        log.info("[{}]算账step1，保存工单算账", orderWork.getWorkId());
        OrderWork accountOrderWork = new OrderWork();
        accountOrderWork.setOrderId(accountDIO.getOrderId());
        accountOrderWork.setWorkId(accountDIO.getWorkId());
        accountOrderWork.setAccountTime(DateUtil.getNow());
        accountOrderWork.setAccounterId((long) GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        accountOrderWork.setStatus(OrderStatusConsts.WORK_STATUS_ACCOUNT);
        accountOrderWork.setResultStatus(OrderStatusConsts.WORK_RESULT_FAIL);
        accountOrderWork.setCurrentRemark(remark);
        accountOrderWork.setAccountId((long)GlobalConsts.NONE);
        financeWorkService.updateAccount(accountOrderWork);
        // 写日志设置状态
        accountDIO.setStatus(accountOrderWork.getStatus());
        accountDIO.setLogContent(remark);
    }


    private boolean canBonus(OrderWork orderWork) {
        if (Objects.equals(orderWork.getServCategId(), 1011)) {
            log.info("工单服务分类为新机销售，不参与加单奖励");
            return false;
        }
        // 加单奖励，发送队列到ERP（成功的新单，无退款记录的师傅加单）
        boolean canBonus = Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)
                && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_SUCCESS)
                && NumberUtil.isNullOrZero(orderWork.getRefundTargetWorkId())
                && Objects.equals(orderWork.getRecommenderType(), GlobalConsts.OPERATE_USER_TYPE_MASTER)
                && NumberUtil.isNotNullOrZero(orderWork.getRecommenderId());

        if (!canBonus) {
            log.info("工程师恶意加单奖励不满足：成功的新单，无退款记录的师傅加单");
            return false;
        }

        // B1的订单下单用户手机号和下单对应的前台产品和A1订单的对应前台产品一模一样
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderWork.getOrderId());

        String receiveTimeSpan = DateUtil.getDateStartString(DateUtil.toString(DateUtil.addDays(orderWork.getReceiveTime(), -3))) + "," + DateUtil.toString(orderWork.getReceiveTime(), DateUtil.FORMAT_DEFAULT);

        OrderWorkQuery query = new OrderWorkQuery();
        query.setPermit(GlobalConsts.NO);
        query.setShowProductId(orderWork.getShowProductId());
        query.setConcatPhone(orderDetail.getTelephone());
        query.setReceiveTime(receiveTimeSpan);
        query.setWorkResultStatusList(Lists.newArrayList(OrderStatusConsts.WORK_RESULT_FAIL, OrderStatusConsts.WORK_RESULT_DISCARD));
        Integer count = orderWorkListBService.countOrderWorkByQuery(query);
        log.info("工程师恶意加单奖励工单查询：条件：{}， 结果：{}", JSON.toJSONString(query), count);

        boolean countJug = orderWork.getResultStatus().equals(OrderStatusConsts.WORK_RESULT_FAIL) || orderWork.getResultStatus().equals(OrderStatusConsts.WORK_RESULT_DISCARD);

        if (countJug) {
            return  (count < 2) && canBonus;
        } else {
            return  (count < 1) && canBonus;
        }
    }


    /**
     * 计算渠道费
     *
     * @param orderWork
     * @return
     */
    private Integer calcChannelAmount(OrderWork orderWork) {
        log.info("工单[{}]开始计算渠道费", orderWork.getWorkId());
        // 计算渠道费
        Integer channelAmount = null;
        com.zmn.common.dto2.ResponseDTO<ChannelCommissionDRO> channelProductDROResponseDTO = channelCommissionParamListRemoteService
                .getByServIdAndChannelId(orderWork.getChannelId(),
                        orderWork.getServCategId());
        ChannelCommissionDRO channelProductDRO = channelProductDROResponseDTO.getData();
        if (channelProductDROResponseDTO.isSuccess() && channelProductDRO != null
                && channelProductDRO.getCommission() != null) {
            Double commission = channelProductDRO.getCommission();
            log.info("工单[{}]有渠道提成配置[{}],[{}]", orderWork.getWorkId(), channelProductDRO.getCommissionType(),
                    commission);
            // 比例返佣
            if (Objects.equals(channelProductDRO.getCommissionType(), 1)) {
                double rate = MathUtil.div(commission, 100, 2);
                channelAmount = Double
                        .valueOf(MathUtil.mul(Optional.ofNullable(orderWork.getTotalAmount()).orElse(0), rate))
                        .intValue();
            }
            // 固定金额返佣
            else if (Objects.equals(channelProductDRO.getCommissionType(), 2)) {
                channelAmount = commission.intValue();
            }
        }
        log.info("工单[{}]渠道费[{}]", orderWork.getWorkId(), channelAmount);
        return channelAmount;
    }



    private void processLog(OrderWork orderWork, ZsSyncAccountDIO accountDIO) throws OmsBaseException {
        if (Objects.isNull(accountDIO.getLogDIO())) {
            throw new OmsBaseException("日志信息不能为空");
        }

        // 判断服务商类型
        Integer spType = orderWork.getManageCompanyType();

        AccountLogDIO logDIO = accountDIO.getLogDIO();
        StringBuilder sb = new StringBuilder();

        // 判断工单类型
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW) && Objects.equals(spType, CompanyConsts.COMPANY_TYPE_SERVICE_OCO) && CollectionUtil.isNotNullOrEmpty(logDIO.getEngineerList())) {
            sb.append("新单-工程师明细：").append("\n");
            logDIO.getEngineerList().forEach(engineer -> {
                // 计算相关金额
                Integer baseShare = engineer.getBasicShareAmount();

                AccountLogRewardDIO rewardDIO = Optional.ofNullable(engineer.getRewardDIO()).orElse(new AccountLogRewardDIO());
                Integer perfPart = sum(rewardDIO.getFavorableComment(), rewardDIO.getComgpleteIn24(), rewardDIO.getContactOnTime(), rewardDIO.getEvaluationScore(), rewardDIO.getPayOnTime(), rewardDIO.getPhoto(), rewardDIO.getReservationOnTime(), rewardDIO.getVisit(), engineer.getComprehensivePerf(), rewardDIO.getTariffBonus());

                AccountLogSubsidyDIO subsidyDIO = Optional.ofNullable(engineer.getSubsidyDIO()).orElse(new AccountLogSubsidyDIO());
                Integer susidyPart = sum(subsidyDIO.getArea(), subsidyDIO.getDistance(), subsidyDIO.getExpedited(), subsidyDIO.getFcOrCh());

                Integer share = sum(baseShare, engineer.getComprehensivePerf());

                AccountLogDiscountDIO discount = Optional.ofNullable(engineer.getDiscountDIO()).orElse(new AccountLogDiscountDIO());

                Integer discountShare = sum(discount.getArtificialPreferences(), discount.getIntegralCost(), discount.getVoucherShare());

                Integer deductionPart = sum(engineer.getDepositCost(), engineer.getInsuranceCost() ,engineer.getHelpCost());

                Integer cooperationShare = sum(engineer.getCooperationTimePerf(), engineer.getTechLevelPerf(), engineer.getStarLevelPerf());

                Integer disAndDed = sum(discountShare, deductionPart);

                sb.append(engineer.getEngineerName()).append("(").append(Objects.equals(engineer.getEngineerType(), OrderConsts.ORDER_MASTER_TYPE_MAIN) ? "主工程师" : "从工程师").append(")\n");


                sb.append("工程师合作奖励：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(cooperationShare), "0")).append(";\n");
                sb.append("合作时长绩效金额：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(engineer.getCooperationTimePerf()), "0")).append(",");
                sb.append("技术等级绩效金额：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(engineer.getTechLevelPerf()), "0")).append(",");
                sb.append("星级评分绩效金额：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(engineer.getStarLevelPerf()), "0")).append(";\n");

                sb.append("工程师提留金额=")
                        .append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(engineer.getRetention()), "0"))
                        .append("\n");

                sb.append("工程师分润金额=")
                        .append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(share), "0"))
                        .append("(明细如下)\n");
                sb.append("工程师基础分润：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(baseShare), "0")).append(",");
                sb.append("标准照片奖励金：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getPhoto()), "0")).append(",");
                sb.append("准时上门奖励金：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getVisit()), "0")).append(",");
                sb.append("评价得分奖励金：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getEvaluationScore()), "0")).append(",");
                sb.append("及时联系奖励金：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getContactOnTime()), "0")).append(",");
                sb.append("及时预约奖励金：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getReservationOnTime()), "0")).append(",");
                sb.append("现场支付奖励金：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getPayOnTime()), "0")).append(",");
                sb.append("24小时完成奖励金：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getComgpleteIn24()), "0")).append(",");
                sb.append("好评设置奖励金：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getFavorableComment()), "0")).append(",");
                sb.append("使用计价器奖励金：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getTariffBonus()), "0")).append(",");
                sb.append("综合绩效金额：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(engineer.getComprehensivePerf()), "0")).append(";\n");
                sb.append("特殊补贴：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(subsidyDIO.getSpecial()), "0")).append(",");
                sb.append("时间段补贴：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(subsidyDIO.getPeriod()), "0")).append(",");
                sb.append("远程补贴：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(subsidyDIO.getDistance()), "0")).append(",");
                sb.append("厂家/渠道补贴：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(subsidyDIO.getFcOrCh()), "0")).append(",");
                sb.append("加急补贴：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(subsidyDIO.getExpedited()), "0")).append(",");
                sb.append("区域补贴：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(subsidyDIO.getArea()), "0")).append(";\n");
                sb.append("分摊及扣减=")
                        .append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(disAndDed), "0"))
                        .append("(明细如下)\n");
                sb.append("分摊优惠券减免：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(discount.getVoucherShare()), "0")).append(",");
                sb.append("分摊优惠减免：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(discount.getArtificialPreferences()), "0")).append(",");
                sb.append("分摊积分减免：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(discount.getIntegralCost()), "0")).append(";\n");
                sb.append("质保金：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(engineer.getDepositCost()), "0")).append(",");
                sb.append("保险费：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(engineer.getInsuranceCost()), "0")).append(",");
                sb.append("保险互助金：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(engineer.getHelpCost()), "0")).append(";\n");
                sb.append("非厂商配件金额：");
                sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(engineer.getPartAmount()), "0")).append(";\n\n");
            });
        } // 判断工单类型
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW) && Objects.equals(spType, CompanyConsts.COMPANY_TYPE_SERVICE_NOT_OCO) && Objects.nonNull(logDIO.getSp())) {
            sb.append("新单-服务商明细：").append("\n");

            AccountLogSpDIO spDIO = logDIO.getSp();
            // 计算相关金额
            Integer baseShare = spDIO.getBasicShareAmount();

            AccountLogRewardDIO rewardDIO = Optional.ofNullable(spDIO.getRewardDIO()).orElse(new AccountLogRewardDIO());
            Integer perfPart = sum(rewardDIO.getFavorableComment(), rewardDIO.getComgpleteIn24(), rewardDIO.getContactOnTime(), rewardDIO.getEvaluationScore(), rewardDIO.getPayOnTime(), rewardDIO.getPhoto(), rewardDIO.getReservationOnTime(), rewardDIO.getVisit(), rewardDIO.getTariffBonus());

            AccountLogSubsidyDIO subsidyDIO = Optional.ofNullable(spDIO.getSubsidyDIO()).orElse(new AccountLogSubsidyDIO());
            Integer susidyPart = sum(subsidyDIO.getArea(), subsidyDIO.getDistance(), subsidyDIO.getExpedited(), subsidyDIO.getFcOrCh());

            Integer share = sum(baseShare, spDIO.getPerfAmount());

            AccountLogDiscountDIO discountDIO = Optional.ofNullable(spDIO.getDiscountDIO()).orElse(new AccountLogDiscountDIO());
            Integer discountShare = sum(discountDIO.getArtificialPreferences(), discountDIO.getIntegralCost(), discountDIO.getVoucherShare());

            Integer deductionPart = spDIO.getDepositCost();

            Integer disAndDed = sum(discountShare, deductionPart);

            sb.append(spDIO.getSpName()).append(")\n");
            sb.append("服务商提留金额=")
                    .append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(spDIO.getRetention()), "0"))
                    .append("\n");

            sb.append("服务商分润金额=")
                    .append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(share), "0"))
                    .append("(明细如下)\n");
            sb.append("服务商基础分润：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(baseShare), "0")).append(",");
            sb.append("标准照片奖励金：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getPhoto()), "0")).append(",");
            sb.append("准时上门奖励金：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getVisit()), "0")).append(",");
            sb.append("评价得分奖励金：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getEvaluationScore()), "0")).append(",");
            sb.append("及时联系奖励金：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getContactOnTime()), "0")).append(",");
            sb.append("及时预约奖励金：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getReservationOnTime()), "0")).append(",");
            sb.append("现场支付奖励金：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getPayOnTime()), "0")).append(",");
            sb.append("24小时完成奖励金：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getComgpleteIn24()), "0")).append(",");
            sb.append("好评设置奖励金：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getFavorableComment()), "0")).append(",");
            sb.append("使用计价器奖励金：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(rewardDIO.getTariffBonus()), "0")).append(",");
            sb.append("服务商综合分润金额：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(spDIO.getPerfAmount()), "0")).append(",");
            sb.append("特殊补贴：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(subsidyDIO.getSpecial()), "0")).append(",");
            sb.append("时间段补贴：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(subsidyDIO.getPeriod()), "0")).append(",");
            sb.append("远程补贴：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(subsidyDIO.getDistance()), "0")).append(",");
            sb.append("厂家/渠道补贴：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(subsidyDIO.getFcOrCh()), "0")).append(",");
            sb.append("加急补贴：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(subsidyDIO.getExpedited()), "0")).append(",");
            sb.append("区域补贴：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(subsidyDIO.getArea()), "0")).append(";\n");
            sb.append("分摊及扣减=")
                    .append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(disAndDed), "0"))
                    .append("(明细如下)\n");
            sb.append("分摊优惠券减免：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(discountDIO.getVoucherShare()), "0")).append(",");
            sb.append("分摊优惠减免：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(discountDIO.getArtificialPreferences()), "0")).append(",");
            sb.append("分摊积分减免：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(discountDIO.getIntegralCost()), "0")).append(";\n");
            sb.append("质保金：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(spDIO.getDepositCost()), "0")).append(";\n");
            sb.append("非厂商配件金额：");
            sb.append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(spDIO.getPartAmount()), "0")).append(";\n\n");
        }
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK) && CollectionUtil.isNotNullOrEmpty(logDIO.getEngineerList())) {
            sb.append("返修单-工程师:\n");
            sb.append("原单工程师扣款:\n");
            if (CollectionUtil.isNotNullOrEmpty(logDIO.getOriginalEngineerList())) {
                logDIO.getOriginalEngineerList().forEach(engineer -> {
                    sb.append(engineer.getEngineerName()).append("(").append(Objects.equals(engineer.getEngineerType(), OrderConsts.ORDER_MASTER_TYPE_MAIN) ? "主" : "从").append(")-扣款：").append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(engineer.getAmount()), "0")).append("\n");
                });
            }
            sb.append("原单工程师奖励:\n");
            if (CollectionUtil.isNotNullOrEmpty(logDIO.getEngineerList())) {
                logDIO.getEngineerList().forEach(engineer -> {
                    sb.append(engineer.getEngineerName()).append("(").append(Objects.equals(engineer.getEngineerType(), OrderConsts.ORDER_MASTER_TYPE_MAIN) ? "主" : "从").append(")-奖励：").append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(engineer.getAmount()), "0")).append("\n");
                });
            }
        }
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK) && Objects.nonNull(logDIO.getOriginalSp())) {
            sb.append("返修单-服务商:\n");
            sb.append("原单服务商扣款:\n");
            sb.append(logDIO.getOriginalSp().getSpName()).append("-扣款：").append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(logDIO.getOriginalSp().getAmount()), "0")).append("\n");
            sb.append("返修单服务商奖励:\n");
            sb.append(logDIO.getOriginalSp().getSpName()).append("-奖励：").append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(logDIO.getSp().getAmount()), "0")).append("\n");
        }
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REFUND)) {
            sb.append("退款单-服务主体承担退款").append("\n");
        }
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REFUND) && Objects.nonNull(logDIO.getSp())) {
            sb.append("退款服务商：").append(logDIO.getSp().getSpName()).append("\n");
            sb.append("服务商退款：").append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(logDIO.getSp().getRetention()), "0")).append("\n");
        }
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REFUND) && Objects.nonNull(logDIO.getSupervisor())) {
            sb.append("退款主管：").append(logDIO.getSupervisor().getSupervisorName()).append("\n");
            sb.append("主管退款：").append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(logDIO.getSupervisor().getSupervisorAmount()), "0")).append("\n");
        }
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REFUND) && CollectionUtil.isNotNullOrEmpty(logDIO.getEngineerList())) {
            sb.append("退款单-工程师:\n");
            if (CollectionUtil.isNotNullOrEmpty(logDIO.getEngineerList())) {
                logDIO.getEngineerList().forEach(engineer -> {
                    sb.append("退款工程师：").append(engineer.getEngineerName()).append("(").append(Objects.equals(engineer.getEngineerType(), OrderConsts.ORDER_MASTER_TYPE_MAIN) ? "主" : "从").append(")").append("\n");
                    sb.append("工程师退款：").append(StringUtils.defaultIfBlank(MoneyUtil.parseToYuanStr(engineer.getAmount()), "0")).append("\n");
                });
            }
        }

        accountDIO.setLogContent(sb.toString());

    }

    private Integer sum(Integer... nums) {
        Integer result = 0;
        for (Integer num : nums) {
            result += Optional.ofNullable(num).orElse(0);
        }
        return result;
    }

    private void sendInvoiceInfo(OrderWork orderWork, OmsOperator operator) {
        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REFUND)) {
            return;
        }
        InvoiceInfoRefundBO bo = new InvoiceInfoRefundBO();
        bo.setOrderId(orderWork.getOrderId());
        bo.setBillId(orderWork.getWorkId());
        bo.setOriginalBillId(orderWork.getOriginalId());
        bo.setInvoiceAmount(Math.abs(orderWork.getTotalAmount()));
        bo.setOperator(operator.getOperator());
        bo.setOperatorId(operator.getOperatorId().intValue());

        String json = JSON.toJSONString(bo);
        log.info("退款单 自动开发票-发送ERP队列 [{}] topic [{}] tag [{}]", json, MessageQueueTopicConstant.ZMN_TOPIC_INVOICE, INVOICE_MQ_TAG);
        String key = String.valueOf(orderWork.getWorkId());
        zmnMQSender.send(MessageQueueTopicConstant.ZMN_TOPIC_INVOICE, INVOICE_MQ_TAG, key, json);
    }

    private void sendAddMasterBonus(OrderWork orderWork) throws OmsBaseException {
        AddMoreOrderBonusDTO addMoreOrderBonusDTO = new AddMoreOrderBonusDTO();
        addMoreOrderBonusDTO.setPlat(orderWork.getPlat());
        addMoreOrderBonusDTO.setBizType(orderWork.getBizType());
        addMoreOrderBonusDTO.setMasterId(orderWork.getRecommenderId().intValue());
        addMoreOrderBonusDTO.setTimesCardAmount(orderWork.getDiscountPrepayAmount());
        // 师傅名
        // todo fubiao
        log.info("sendAddMasterBonus#getEngineerDetailById 入参 [{}]",orderWork.getRecommenderId().intValue());
        ResponseDTO<ForeignEngineerDetailInfoDRO> remoteRespDTO = engineerListRemoteService.getEngineerDetailById(orderWork.getRecommenderId().intValue());
        log.info("sendAddMasterBonus#getEngineerDetailById 出参 [{}]",JSON.toJSONString(remoteRespDTO));
        ForeignEngineerDetailInfoDRO engineerDRO = remoteRespDTO.getData();
        if (engineerDRO != null) {
            addMoreOrderBonusDTO.setMasterName(engineerDRO.getRealName());
            addMoreOrderBonusDTO.setManageCompanyId(engineerDRO.getSpCompanyId());
            com.zmn.common.dto2.ResponseDTO<CompanyDRO> companyDROResponseDTO = companyListRemoteService.getCompanyDROById(engineerDRO.getSpCompanyId());
            if (companyDROResponseDTO.getData() != null) {
                addMoreOrderBonusDTO.setManageCompanyName(companyDROResponseDTO.getData().getFullName());
            }
        } else {
            addMoreOrderBonusDTO.setMasterName("未知名");
            addMoreOrderBonusDTO.setManageCompanyId(orderWork.getManageCompanyId());
            addMoreOrderBonusDTO.setManageCompanyName(orderWork.getManageCompanyName());
        }

        addMoreOrderBonusDTO.setOrderId(orderWork.getOrderId());
        addMoreOrderBonusDTO.setCheckoutTime(orderWork.getCheckoutTime());
        addMoreOrderBonusDTO.setProductGroupId(orderWork.getServProductGroupId());
        // 内部结算价
        List<OrderServiceItem> orderServiceItems = orderServiceItemService.listByOrderId(orderWork.getOrderId());
        int internalSettlementPrice = 0;
        if (CollectionUtil.isNotNullOrEmpty(orderServiceItems)) {
            internalSettlementPrice = orderServiceItems.stream().filter(e -> NumberUtil.isNotNullOrZero(e.getInternalSettlementPrice())).mapToInt(e -> e.getInternalSettlementPrice() * e.getNumber()).sum();
        }
        addMoreOrderBonusDTO.setInternalStatementAmount(NumberUtil.isNotNullOrZero(internalSettlementPrice) ? internalSettlementPrice : orderWork.getOriginalAmount());

        // 配件金额
        List<OrderPart> orderParts = orderPartService.listByOrderId(orderWork.getOrderId());
        Integer partAmount = orderParts.stream().mapToInt(part -> {
            return com.zmn.oms.common.utils.MathUtil.amountMultiplyNumber(part.getPrice(), part.getNumber());
        }).sum();
        addMoreOrderBonusDTO.setPartAmount(partAmount);
        Integer inPartAmount = orderParts.stream().filter(e->Objects.equals(e.getPartType(),OrderConsts.PART_TYPE_SOURCING_IN)).mapToInt(part -> {
            return com.zmn.oms.common.utils.MathUtil.amountMultiplyNumber(part.getPrice(), part.getNumber());
        }).sum();
        addMoreOrderBonusDTO.setInsourcePartAmount(inPartAmount);
        addMoreOrderBonusDTO.setDiscountAmount(orderWork.getDiscountAmount());

        addMoreOrderBonusDTO.setServCategId(orderWork.getServCategId());
        // 前后台目前一致
        addMoreOrderBonusDTO.setServCategName(orderWork.getShowServCategName());
        addMoreOrderBonusDTO.setServMajorEngineerId(String.valueOf(orderWork.getMasterId()));
        addMoreOrderBonusDTO.setServMajorEngineerName(orderWork.getMasterName());
        addMoreOrderBonusDTO.setAddMoreOrderTime(orderWork.getReceiveTime());
        addMoreOrderBonusDTO.setCategOneId(orderWork.getCategOneId());
        addMoreOrderBonusDTO.setOrderReceiveAmount(orderWork.getTotalAmount());
        addMoreOrderBonusDTO.setPartsReimburseStatus(orderWork.getPartReimburseStatus());
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderWork.getOrderId());
        addMoreOrderBonusDTO.setProductInf(orderDetail.getProductInfo());


        log.info("加单奖励-发送ERP队列[{}]", addMoreOrderBonusDTO);
        String json = JSON.toJSONString(addMoreOrderBonusDTO);
        String key = String.valueOf(addMoreOrderBonusDTO.getOrderId());
        zmnMQSender.send(MessageQueueTopicConstant.ZMN_TOPIC_ERP, MessageQueueTagConsts.ZMN_ERP_MASTER_ADDORDER_BONUS, key, json);
    }

}
